﻿using System;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Core;

namespace zijian666.Converts.Factory;

/// <summary>
/// 为已实例化的转换器包装一个工厂对象
/// </summary>
public sealed class InstantiatedConvertorFactory : IConvertorFactory
{
    /// <summary>
    /// 转换器
    /// </summary>
    private readonly object _convertor;
    /// <summary>
    /// 转换器转出类型
    /// </summary>
    private readonly Type _outputType;

    /// <summary>
    /// 构造函数, 创建一个工厂
    /// </summary>
    /// <param name="convertor">转换器</param>
    /// <param name="outputType">转换器转出类型</param>
    internal InstantiatedConvertorFactory(object convertor, Type outputType)
    {
        _convertor = convertor ?? throw new ArgumentNullException(nameof(convertor));
        _outputType = outputType ?? throw new ArgumentNullException(nameof(outputType));
    }

    /// <summary>
    /// 创建工厂
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="convertor"></param>
    /// <returns></returns>
    public static IConvertorFactory BuildFactory<T>(IConvertor<T> convertor) => new InstantiatedConvertorFactory(convertor, typeof(T));

    /// <inheritdoc/>
    public MatchedConvertor<T> Create<T>()
    {
        if (_convertor is IConvertor<T> conv)
        {
            return new MatchedConvertor<T>(conv, MacthedType.Equals);
        }
        else if (_outputType.IsAssignableFrom(typeof(T)))
        {
            var proxyType = typeof(ProxyConvertor<,>).MakeGenericType(_outputType, typeof(T));
            var proxy = (IConvertor<T>)Activator.CreateInstance(proxyType, _convertor);
            return new MatchedConvertor<T>(proxy, MacthedType.Acceptable);
        }
        return default;
    }
}
